package com.neofinance.reactdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.function.context.FunctionEntry;
import org.springframework.cloud.function.context.FunctionScan;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;

import java.time.Duration;
import java.util.Date;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * Created by Michael Chen on 2017-8-22.
 */
@SpringBootApplication
@FunctionScan
@RestController
public class ActDemoServiceApplication {

    @Bean
    public MyKtPoint getKtpoint() {
        return new MyKtPoint("DefaultKtPoint");
    }

    @Bean
    @FunctionEntry("up")
    public Function<String, ApiResponse<String>> toUpperCase() {
        return str -> new ApiResponse<String>("/up", ApiResponse.CODE.SUCCESS, "转换为大写字母", str.toUpperCase());
    }

    @Bean
    @FunctionEntry("cloudEvent")
    public Function<Flux<Long>, Flux<Event>> getEventFlux() {
        return flux -> flux.map(id -> new Event(id, new Date(), "Event Flux from Cloud"));
    }

    @GetMapping("/events/{id}")
    Mono<Event> eventById(@PathVariable long id) {
        return Mono.just(new Event(id, new Date(), "message"));
    }

    @GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, value = "/events")
    Flux<Event> events() {
        Flux<Event> eventFlux = Flux.fromStream(Stream.generate(() -> new Event(System.currentTimeMillis(), new Date(), "message")));
        Flux<Long> durationFlux = Flux.interval(Duration.ofSeconds(1));
        return Flux.zip(eventFlux, durationFlux).map(Tuple2::getT1);
    }

    public static void main(String[] args) {
        SpringApplication.run(ActDemoServiceApplication.class, args);
    }
}

